package cn.kgc.security;

import cn.kgc.entity.CustomerUser;
import cn.kgc.entity.Users;
import cn.kgc.form.LoginForm;
import cn.kgc.util.JwtUtil;
import cn.kgc.util.ResponseUtil;
import cn.kgc.util.Result;
import cn.kgc.util.ResultConstant;
import cn.kgc.util.exception.HttpException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * 登录认证的过滤器
 */
public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private JwtUtil jwtUtil;

    /**
     * 登录认证的过滤器构造方法(没有让Spring框架管理 后面自己创建对象使用)
     *
     * @param authenticationManager 认证管理器
     * @param jwtUtil               jwt工具类
     */

    public AuthenticationFilter(AuthenticationManager authenticationManager,
                                JwtUtil jwtUtil) {
        //设置认证管理器
        this.setAuthenticationManager(authenticationManager);
        //给jwtUtil属性赋值
        this.jwtUtil = jwtUtil;
        //指定登录的请求是否支持post请求
        this.setPostOnly(false);
        //登录请求的路径
        this.setRequiresAuthenticationRequestMatcher(
                new AntPathRequestMatcher("/users/login", "POST")
        );
    }


    //如果认证成功，执行此方法
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                            FilterChain chain, Authentication authResult) throws IOException, ServletException {
        //获得登录成功的用户信息
        CustomerUser customerUser = (CustomerUser) authResult.getPrincipal();
        Users users = customerUser.getUsers();
        //判断用户的状态,用户的状态是离职状态，返回错误信息
        if (customerUser.getUsers().getState() == 2) {
            ResponseUtil.setResponse(response, Result.error(new HttpException(ResultConstant.LOGIN_ERROR))
            );
        }
        //如果用户的状态是在职(试用期 转正)生成token令牌 将用户的id 用户的名字返回给前端
        Integer userId = users.getUserId();
        String token = jwtUtil.generateAccessToken(userId + "");
        Map<String, Object> map = Map.of(
                "userid", userId,
                "username", users.getUserName(),
                "token", token
        );
        ResponseUtil.setResponse(response, Result.success(map));
    }

    //如果认证失败，执行此方法
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        ResponseUtil.setResponse(response,
                Result.error(new HttpException(ResultConstant.LOGIN_ERROR)));
    }

    /**
     * 登录认证
     *
     * @param request
     * @param response
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        try {
            //从请求中获得loginForm对象
            LoginForm loginForm = new ObjectMapper().readValue(request.getInputStream(), LoginForm.class);
            //将loginForm对象封装到UsernamePasswordAuthenticationToken对象中
            Authentication authentication = new UsernamePasswordAuthenticationToken(
                    loginForm.getUserName(),
                    loginForm.getPassword()
            );
            //调用认证管理器中authenticate方法进行认证
            return getAuthenticationManager().authenticate(authentication);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
